import * as Cesium from 'cesium';
class SlopeAspectAnalysis {
  constructor(viewer, options = {}) {
    this.viewer = viewer;
    this.Cesium = Cesium;
    this.options = options;

    // 默认参数
    this.defaults = {
      slopeColorRamp: this.createSlopeColorRamp(),
      aspectColorRamp: this.createAspectColorRamp(),
      analysisMode: 'slope', // 'slope' 或 'aspect'
      sampleDistance: 10, // 采样点间距(米)
      showSamplePoints: false
    };

    // 合并配置
    this.config = { ...this.defaults, ...options };

    // 分析结果实体
    this.analysisEntity = null;
    this.samplePoints = [];

    // 事件处理器
    this.handler = null;
    this._isAnalyzing = false;
  }

  // 创建坡度颜色渐变
  createSlopeColorRamp() {
    return [
      { value: 0, color: new this.Cesium.Color(0.0, 0.8, 0.0, 0.8) }, // 绿色(低坡度)
      { value: 15, color: new this.Cesium.Color(0.8, 0.8, 0.0, 0.8) }, // 黄色
      { value: 30, color: new this.Cesium.Color(0.8, 0.4, 0.0, 0.8) }, // 橙色
      { value: 45, color: new this.Cesium.Color(0.8, 0.0, 0.0, 0.8) }  // 红色(高坡度)
    ];
  }

  // 创建坡向颜色渐变
  createAspectColorRamp() {
    return [
      { value: 0, color: new this.Cesium.Color(0.5, 0.5, 0.5, 0.8) }, // 灰色(平地)
      { value: 22.5, color: new this.Cesium.Color(0.0, 0.0, 0.8, 0.8) }, // 北
      { value: 67.5, color: new this.Cesium.Color(0.0, 0.5, 0.8, 0.8) }, // 东北
      { value: 112.5, color: new this.Cesium.Color(0.0, 0.8, 0.0, 0.8) }, // 东
      { value: 157.5, color: new this.Cesium.Color(0.8, 0.8, 0.0, 0.8) }, // 东南
      { value: 202.5, color: new this.Cesium.Color(0.8, 0.5, 0.0, 0.8) }, // 南
      { value: 247.5, color: new this.Cesium.Color(0.8, 0.2, 0.0, 0.8) }, // 西南
      { value: 292.5, color: new this.Cesium.Color(0.5, 0.0, 0.8, 0.8) }, // 西
      { value: 337.5, color: new this.Cesium.Color(0.2, 0.0, 0.8, 0.8) }, // 西北
      { value: 360, color: new this.Cesium.Color(0.0, 0.0, 0.8, 0.8) }  // 北
    ];
  }

  // 根据值获取颜色
  getColorFromRamp(value, ramp) {
    if (value === null || isNaN(value)) {
      return new this.Cesium.Color(0, 0, 0, 0); // 透明
    }

    // 找到值所在的区间
    for (let i = 0; i < ramp.length - 1; i++) {
      if (value >= ramp[i].value && value < ramp[i + 1].value) {
        // 线性插值
        const ratio = (value - ramp[i].value) / (ramp[i + 1].value - ramp[i].value);
        return this.Cesium.Color.interpolate(
          ramp[i].color,
          ramp[i + 1].color,
          ratio,
          new this.Cesium.Color()
        );
      }
    }

    // 如果值超出范围，返回最后一个颜色
    return ramp[ramp.length - 1].color;
  }

  // 计算坡度(度)
  calculateSlope(nx, ny, nz) {
    // 坡度 = arctan(sqrt(nx² + ny²) / nz) * 180/π
    const slope = Math.atan(Math.sqrt(nx * nx + ny * ny) / Math.abs(nz)) * (180 / Math.PI);
    return slope;
  }

  // 计算坡向(度)
  calculateAspect(nx, ny) {
    // 坡向 = arctan2(-ny, nx) * 180/π
    let aspect = Math.atan2(-ny, nx) * (180 / Math.PI);

    // 转换为0-360度
    if (aspect < 0) {
      aspect += 360;
    }

    // 平地的坡向定义为-1
    if (nx === 0 && ny === 0) {
      aspect = -1;
    }

    return aspect;
  }

  // 开始分析
  startAnalysis(rectangle) {
    this.clearAnalysis();
    this._isAnalyzing = true;

    // 如果未提供矩形，则使用当前视图范围
    if (!rectangle) {
      rectangle = this.viewer.camera.computeViewRectangle();
    }

    // 创建分析覆盖层
    this.createAnalysisOverlay(rectangle);
  }

  // 创建分析覆盖层
  createAnalysisOverlay(rectangle) {
    const $this = this;
    const ellipsoid = this.viewer.scene.globe.ellipsoid;

    // 计算采样点数量
    const width = this.Cesium.Rectangle.width(rectangle);
    const height = this.Cesium.Rectangle.height(rectangle);

    // 估算采样点数量
    const center = this.Cesium.Rectangle.center(rectangle);
    const centerCartesian = ellipsoid.cartographicToCartesian(center);
    const metersPerDegree = this.estimateMetersPerDegree(center);

    const samplePointsX = Math.ceil(width * metersPerDegree.longitude / this.config.sampleDistance);
    const samplePointsY = Math.ceil(height * metersPerDegree.latitude / this.config.sampleDistance);

    // 创建分析材质
    const material = new this.Cesium.ImageMaterialProperty({
      image: this.generateAnalysisImage(rectangle, samplePointsX, samplePointsY),
      transparent: true
    });

    // 创建矩形实体
    this.analysisEntity = this.viewer.entities.add({
      rectangle: {
        coordinates: rectangle,
        material: material,
        height: 0,
        heightReference: this.Cesium.HeightReference.CLAMP_TO_GROUND
      },
      description: this.generateLegend()
    });
  }

  // 生成分析图像
  generateAnalysisImage(rectangle, samplePointsX, samplePointsY) {
    const $this = this;
    const canvas = document.createElement('canvas');
    canvas.width = samplePointsX;
    canvas.height = samplePointsY;

    const context = canvas.getContext('2d');
    const imageData = context.createImageData(samplePointsX, samplePointsY);
    const data = imageData.data;

    // 异步处理以避免UI阻塞
    return new Promise((resolve, reject) => {
      // 按行处理以优化性能
      let processedRows = 0;

      function processRow(row) {
        if (row >= samplePointsY) {
          context.putImageData(imageData, 0, 0);
          resolve(canvas);
          return;
        }

        const tasks = [];

        for (let col = 0; col < samplePointsX; col++) {
          tasks.push(new Promise((innerResolve) => {
            // 计算经纬度
            const lon = rectangle.west + col * (rectangle.east - rectangle.west) / (samplePointsX - 1);
            const lat = rectangle.north - row * (rectangle.north - rectangle.south) / (samplePointsY - 1);

            const cartographic = this.Cesium.Cartographic.fromRadians(lon, lat);

            // 获取地形法线
            this.viewer.scene.globe.getNormal(cartographic, (normal) => {
              if (normal) {
                const nx = normal.x;
                const ny = normal.y;
                const nz = normal.z;

                let value;

                if (this.config.analysisMode === 'slope') {
                  value = this.calculateSlope(nx, ny, nz);
                } else {
                  value = this.calculateAspect(nx, ny);
                }

                // 获取颜色
                const colorRamp = this.config.analysisMode === 'slope'
                  ? this.config.slopeColorRamp
                  : this.config.aspectColorRamp;

                const color = this.getColorFromRamp(value, colorRamp);

                // 设置像素颜色
                const index = (row * samplePointsX + col) * 4;
                data[index] = Math.round(color.red * 255);
                data[index + 1] = Math.round(color.green * 255);
                data[index + 2] = Math.round(color.blue * 255);
                data[index + 3] = Math.round(color.alpha * 255);

                // 可选地显示采样点
                if (this.config.showSamplePoints) {
                  const cartesian = this.viewer.scene.globe.ellipsoid.cartographicToCartesian(cartographic);
                  const point = this.viewer.entities.add({
                    position: cartesian,
                    point: {
                      pixelSize: 3,
                      color: color
                    },
                    metadata: {
                      type: 'samplePoint',
                      slope: this.config.analysisMode === 'slope' ? value : null,
                      aspect: this.config.analysisMode === 'aspect' ? value : null
                    }
                  });
                  this.samplePoints.push(point);
                }
              }

              innerResolve();
            });
          }));
        }

        // 等待所有列处理完成
        Promise.all(tasks).then(() => {
          processedRows++;

          // 每处理10行更新一次进度
          if (processedRows % 10 === 0 || processedRows === samplePointsY) {
            console.log(`处理进度: ${((processedRows / samplePointsY) * 100).toFixed(1)}%`);
          }

          // 处理下一行
          processRow.call($this, row + 1);
        });
      }

      // 开始处理第一行
      processRow.call(this, 0);
    });
  }

  // 估算每度对应的米数
  estimateMetersPerDegree(cartographic) {
    const ellipsoid = this.viewer.scene.globe.ellipsoid;
    const center = ellipsoid.cartographicToCartesian(cartographic);

    // 计算东西方向(经度)每度的米数
    const east = this.Cesium.Cartographic.fromRadians(
      cartographic.longitude + 0.001,
      cartographic.latitude
    );
    const eastCartesian = ellipsoid.cartographicToCartesian(east);
    const lonMeters = this.Cesium.Cartesian3.distance(center, eastCartesian) * 1000;

    // 计算南北方向(纬度)每度的米数
    const north = this.Cesium.Cartographic.fromRadians(
      cartographic.longitude,
      cartographic.latitude + 0.001
    );
    const northCartesian = ellipsoid.cartographicToCartesian(north);
    const latMeters = this.Cesium.Cartesian3.distance(center, northCartesian) * 1000;

    return {
      longitude: lonMeters,
      latitude: latMeters
    };
  }

  // 生成图例
  generateLegend() {
    let html = `<div style="background-color: rgba(0,0,0,0.7); color: white; padding: 10px; border-radius: 5px;">`;
    html += `<h3>${this.config.analysisMode === 'slope' ? '坡度分析' : '坡向分析'}</h3>`;

    if (this.config.analysisMode === 'slope') {
      // 坡度图例
      html += `<div style="display: flex; flex-direction: column; gap: 5px;">`;
      for (let i = 0; i < this.config.slopeColorRamp.length - 1; i++) {
        const from = this.config.slopeColorRamp[i].value;
        const to = this.config.slopeColorRamp[i + 1].value;
        const color = this.config.slopeColorRamp[i].color;

        html += `<div style="display: flex; align-items: center;">`;
        html += `<div style="width: 20px; height: 20px; background-color: rgba(${Math.round(color.red * 255)},${Math.round(color.green * 255)},${Math.round(color.blue * 255)},${color.alpha}); margin-right: 5px;"></div>`;
        html += `<div>${from.toFixed(0)}° - ${to.toFixed(0)}°</div>`;
        html += `</div>`;
      }
      html += `</div>`;
    } else {
      // 坡向图例
      html += `<div style="display: flex; flex-direction: column; gap: 5px;">`;
      const directions = ['北', '东北', '东', '东南', '南', '西南', '西', '西北', '北'];

      for (let i = 0; i < this.config.aspectColorRamp.length - 1; i++) {
        const from = this.config.aspectColorRamp[i].value;
        const to = this.config.aspectColorRamp[i + 1].value;
        const color = this.config.aspectColorRamp[i].color;
        const direction = directions[i];

        html += `<div style="display: flex; align-items: center;">`;
        html += `<div style="width: 20px; height: 20px; background-color: rgba(${Math.round(color.red * 255)},${Math.round(color.green * 255)},${Math.round(color.blue * 255)},${color.alpha}); margin-right: 5px;"></div>`;
        html += `<div>${direction} (${from.toFixed(0)}° - ${to.toFixed(0)}°)</div>`;
        html += `</div>`;
      }
      html += `</div>`;
    }

    html += `</div>`;
    return html;
  }

  // 设置分析模式
  setAnalysisMode(mode) {
    if (mode === 'slope' || mode === 'aspect') {
      this.config.analysisMode = mode;

      // 如果当前有分析结果，重新生成
      if (this.analysisEntity) {
        const rectangle = this.analysisEntity.rectangle.coordinates.getValue(this.Cesium.JulianDate.now());
        this.clearAnalysis();
        this.createAnalysisOverlay(rectangle);
      }
    }
  }

  // 清除分析结果
  clearAnalysis() {
    if (this.analysisEntity) {
      this.viewer.entities.remove(this.analysisEntity);
      this.analysisEntity = null;
    }

    // 清除采样点
    if (this.samplePoints.length > 0) {
      this.samplePoints.forEach(point => {
        this.viewer.entities.remove(point);
      });
      this.samplePoints = [];
    }

    this._isAnalyzing = false;
  }

  // 启用区域选择分析
  enableRegionSelection() {
    const $this = this;
    let rectanglePoints = [];
    let rectangleEntity = null;

    this.handler = new this.Cesium.ScreenSpaceEventHandler(this.viewer.scene.canvas);

    // 左键点击开始选择
    this.handler.setInputAction((movement) => {
      const cartesian = this.getCatesian3FromPX(movement.position);
      console.log('点击', cartesian);
      if (!cartesian) return;

      if (rectanglePoints.length === 0) {
        // 第一个点
        rectanglePoints.push(cartesian);

        // 创建临时点
        const point = this.viewer.entities.add({
          position: cartesian,
          point: {
            pixelSize: 5,
            color: this.Cesium.Color.WHITE
          }
        });
        rectanglePoints.push(point);
      } else if (rectanglePoints.length === 2) {
        // 第二个点
        rectanglePoints[0] = cartesian;

        // 更新临时点
        rectanglePoints[1].position = cartesian;

        // 创建矩形
        const cartographic1 = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(rectanglePoints[2]);
        const cartographic2 = this.viewer.scene.globe.ellipsoid.cartesianToCartographic(rectanglePoints[0]);

        const rectangle = this.Cesium.Rectangle.fromDegrees(
          Math.min(cartographic1.longitude * this.Cesium.Math.toDegrees(), cartographic2.longitude * this.Cesium.Math.toDegrees()),
          Math.min(cartographic1.latitude * this.Cesium.Math.toDegrees(), cartographic2.latitude * this.Cesium.Math.toDegrees()),
          Math.max(cartographic1.longitude * this.Cesium.Math.toDegrees(), cartographic2.longitude * this.Cesium.Math.toDegrees()),
          Math.max(cartographic1.latitude * this.Cesium.Math.toDegrees(), cartographic2.latitude * this.Cesium.Math.toDegrees())
        );

        if (rectangleEntity) {
          this.viewer.entities.remove(rectangleEntity);
        }

        rectangleEntity = this.viewer.entities.add({
          rectangle: {
            coordinates: rectangle,
            material: new this.Cesium.Color(1, 1, 1, 0.3),
            outline: true,
            outlineColor: this.Cesium.Color.WHITE
          }
        });

        // 存储矩形
        rectanglePoints.push(rectangle);
        rectanglePoints.push(rectangleEntity);
      } else if (rectanglePoints.length === 4) {
        // 第三个点，确认选择
        this.clearAnalysis();

        // 开始分析选定区域
        this.startAnalysis(rectanglePoints[2]);

        // 清理临时实体
        this.viewer.entities.remove(rectanglePoints[1]);
        this.viewer.entities.remove(rectanglePoints[3]);

        // 重置
        rectanglePoints = [];
        this.disableRegionSelection();
      }
    }, this.Cesium.ScreenSpaceEventType.LEFT_CLICK);

    // 右键取消
    this.handler.setInputAction(() => {
      // 清理临时实体
      if (rectanglePoints.length > 0) {
        if (rectanglePoints.length > 1) {
          this.viewer.entities.remove(rectanglePoints[1]);
        }
        if (rectanglePoints.length > 3) {
          this.viewer.entities.remove(rectanglePoints[3]);
        }
      }

      rectanglePoints = [];
      this.disableRegionSelection();
    }, this.Cesium.ScreenSpaceEventType.RIGHT_CLICK);
  }

  // 禁用区域选择
  disableRegionSelection() {
    if (this.handler) {
      this.handler.destroy();
      this.handler = null;
    }
  }

  // 获取屏幕坐标对应的地形坐标
  getCatesian3FromPX(px) {
    var cartesian;
    var ray = this.viewer.camera.getPickRay(px);
    if (!ray) return null;
    cartesian = this.viewer.scene.globe.pick(ray, this.viewer.scene);
    return cartesian;
  }

  // 销毁实例
  destroy() {
    this.clearAnalysis();
    this.disableRegionSelection();

    // 移除所有创建的实体
    if (this.samplePoints && this.samplePoints.length > 0) {
      this.samplePoints.forEach(point => {
        this.viewer.entities.remove(point);
      });
      this.samplePoints = [];
    }
  }
}

export default SlopeAspectAnalysis;